"""
演示如何使用串口读取数据，并绘制出图像。

Stone at GDOU，2020
"""
import math
import time

import serial

from pygame_scope import Scope


# 设置示波器
scope = Scope(sizex=600, sizey=600)
yaxis = scope.axes.yaxis
yaxis.lim_upper = 1.5
yaxis.lim_lower = -1.5
yaxis.tick_step = 1

xaxis = scope.axes.xaxis
xaxis.lim_upper = 1.5
xaxis.lim_lower = -1.5
xaxis.tick_step = 1

scope.panel.min_value = 0
scope.panel.max_value = 4
scope.panel.value = 0

scope.axes.mode_xy = True   # 启用 x-y 模式
cxy = scope.axes.create_curve([255, 0, 255], curve_type='x-y')  # 创建 x-y 曲线对象
cxy.connected = True
cxy.thickness = 2
cxy.draw_points = True
cxy.pt_radius = 2
cxy.n_points = 20   



# 初始化串口
ser = serial.Serial("com4") # 串口号
serial.baudrate = 115200    # 波特率


def parse_line(txt):
    """解析一行文本，以列表的形式返回数据，数据类型为浮点型。
    文本行的格式应为:
        val1, val2, ...
    """
    sep = b','  # 分界符
    
    txt = txt.strip()           # 去除字符串首尾的空白字符
    values = txt.split(sep)     # 分裂出各项数值
    values = [float(x) for x in values]  # 转为浮点数
    
    return values


def gen_data():
    """生成数据"""
    w = 2*math.pi*1    # rad/s, 2πf
    
    while True:
        t = time.time()            # 系统当前时间
        phi = scope.panel.value     # rad, 利用滑块设置初相位
        
        x = math.sin(w*t)
        y = math.cos(3*w*t + phi)
        
        # print("%.3f,\t%.3f" % (x, y))
        yield (x, y)
data_src = gen_data()


def example_1(data):
    """读取串口值，解析后绘制出 x-y 图形。
    换行符/波特率不正确可能造成程序无响应
    
    :param data: 参数 ``data`` 应为生成器。
    """
    # ===== =====
    # 串口模块回环测试，即串口的 RX 接自己的 TX
    # ===== =====
    x, y = next(data)                   # 从生成器获得值
    ser.write(b'%.2f, %.2f \r\n' % (x, y))  # 发送一行数据
    recv = ser.readline()               # 接收一行数据（刚刚发送的）
    pair = parse_line(recv)             # 解析数据
    cxy.append_sample(pair)             # 绘制数据
    
    scope.show()  # 一定要记得调用scope.show()显示结果


def example_2(data):
    """读取串口值，解析后绘制出 y-t 图形。
    换行符/波特率不正确可能造成程序无响应
    
    :param data: 参数 ``data`` 应为生成器。
    """
    # ===== =====
    # 串口模块回环测试，即串口的 RX 接自己的 TX
    # ===== =====
    x, y = next(data)                   # 从生成器获得值
    ser.write(b'%.2f, %.2f \r\n' % (x, y))  # 发送一行数据
    recv = ser.readline()               # 接收一行数据（刚刚发送的）
    pair = parse_line(recv)             # 解析数据
    scope.append_sample(pair[1])        # 绘制数据
    
    scope.show()  # 一定要记得调用scope.show()显示结果
    

def fake_main():
    example_1(data_src)
    # example_2(data_src)


if __name__ == '__main__':
    scope.mainloop(user_task=fake_main)